package com.captjack.netty.httpserver.handler;

import com.alibaba.fastjson.JSONObject;
import com.captjack.netty.httpserver.constant.NettyServerHandlerConstant;
import com.captjack.netty.httpserver.entity.CommonResult;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpHeaderNames;
import io.netty.handler.codec.http.HttpHeaderValues;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.HttpUtil;
import io.netty.handler.codec.http.HttpVersion;
import lombok.extern.slf4j.Slf4j;

/**
 * @author admin
 */
@Slf4j
@ChannelHandler.Sharable
public final class NettyHttpServerHandler extends ChannelInboundHandlerAdapter {

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        try {
            if (msg instanceof HttpRequest) {
                if (1 == 1) {
                    throw new RuntimeException("asgsag");
                }
                //
                HttpRequest request = (HttpRequest) msg;
                //
                HttpMethod reqMethod = request.method();
                // 根据请求类型分发
                if (reqMethod == HttpMethod.GET) {
                    handlerGetReq(ctx, request);
                } else if (reqMethod == HttpMethod.POST) {
                    handlerPostReq(ctx, request);
                } else {
                    // 是否keepAlive
                    boolean keepAlive = HttpUtil.isKeepAlive(request);
                    // 暂不支持此类请求
                    writeStringToResponse(ctx, CommonResult.builder().code(500).msg("server not support this request method! " + reqMethod.name()).build(), keepAlive);
                }
                // 重定向处理
//                if (httpResponse.status().equals(HttpResponseStatus.FOUND)) {
//                    httpResponse.headers().set(HttpHeaderNames.LOCATION, "https://www.baidu.com/");
//                }
            }
        } catch (Exception e) {
            log.error("", e);
            // 返回异常
            exceptionAdvice(ctx);
        }
    }

    /**
     * 处理get请求
     *
     * @param ctx     ctx
     * @param request 请求
     */
    private void handlerGetReq(ChannelHandlerContext ctx, HttpRequest request) {
        // 是否keepAlive
        boolean keepAlive = HttpUtil.isKeepAlive(request);
        //
        writeStringToResponse(ctx, CommonResult.builder().code(200).msg("get request already deal!").build(), keepAlive);
    }

    /**
     * 处理post请求
     *
     * @param ctx     ctx
     * @param request 请求
     */
    private void handlerPostReq(ChannelHandlerContext ctx, HttpRequest request) {
        // 是否keepAlive
        boolean keepAlive = HttpUtil.isKeepAlive(request);
        //
        writeStringToResponse(ctx, CommonResult.builder().code(200).msg("post request already deal!").build(), keepAlive);
    }

    /**
     * 写返回流
     *
     * @param ctx       ctx
     * @param content   内容
     * @param keepAlive keepAlive
     */
    private void writeStringToResponse(ChannelHandlerContext ctx, Object content, boolean keepAlive) {
        writeStringToResponse(ctx, JSONObject.toJSONString(content), keepAlive);
    }

    /**
     * 统一异常处理
     *
     * @param ctx ctx
     */
    private void exceptionAdvice(ChannelHandlerContext ctx) {
        //
        writeStringToResponse(ctx, NettyServerHandlerConstant.COMMON_EXCEPTION_RETURN_CONTENT, false);
    }

    /**
     * 写返回流
     *
     * @param ctx       ctx
     * @param content   内容
     * @param keepAlive keepAlive
     */
    private void writeStringToResponse(ChannelHandlerContext ctx, String content, boolean keepAlive) {
        FullHttpResponse httpResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
        //
        httpResponse.content().writeBytes(content.getBytes());
        //
        httpResponse.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/html;charset=UTF-8");
        httpResponse.headers().setInt(HttpHeaderNames.CONTENT_LENGTH, httpResponse.content().readableBytes());
        //
        if (keepAlive) {
            httpResponse.headers().set(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE);
            //
            ctx.writeAndFlush(httpResponse);
        } else {
            ctx.writeAndFlush(httpResponse).addListener(ChannelFutureListener.CLOSE);
        }
    }

}
